﻿using LightCAD.Core;
using LightCAD.Core.Elements;
using LightCAD.MathLib;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using Teigha.DatabaseServices;
using Teigha.Geometry;
using static LightCAD.Core.Elements.LcPolyLine;

namespace LightCAD.ImpExpDwg
{
    public static class ConvertToLightCAD
    {
        public static LcElement? ConverEntityToLcElement(LcDocument lcDocument, Entity entity)
        {
            LcElement? lcElement = null;
            #region 元素转换
            if (entity is Line)
            {
                var line = entity as Line;
                lcElement = ConvertLineToLcLine(lcDocument, line);
            }
            else if (entity is Arc)
            {
                var arc = entity as Arc;
                lcElement = ConvertArcToLcArc(lcDocument, arc);
            }
            else if (entity is Polyline)
            {
                var polyline = entity as Polyline;
                lcElement = ConvertPolylineToLcPolyline(lcDocument, polyline);
            }
            else if (entity is Ellipse)
            {
                var ellipse = entity as Ellipse;
                lcElement = ConvertEllipseToLcEllipse(lcDocument, ellipse);
            }
            else if (entity is Circle)
            {
                var circle = entity as Circle;
                lcElement = ConvertCircleToLcCircle(lcDocument, circle);
            }
            else if (entity is Dimension)
            {
                var dimension = entity as Dimension;
                lcElement = ConvertDimToLcDim(lcDocument, dimension);
            }
            else if (entity is DBText)
            {
                var text = entity as DBText;
                LcText lcText = lcDocument.CreateObject<LcText>();
                lcText.Start = text.Position.ToVecror2d();
                lcText.TextStart = text.Position.ToVecror2d();
                lcText.Boxstart = text.Position.ToVecror2d();
                lcText.text = text.TextString; 
                lcText.Heigh = text.Height;
                //字体
                lcText.Typeface ="黑体";
                //向量
                //lcText.XLpoint = new Vector2(text.Normal.X, text.Normal.Y); 
                //默认值
                lcText.Tilt = 0;
                lcText.Widthfactor = 1;
                //计算文字角度
                lcText.Rotate = text.Rotation;
                lcText.Alignment = "左对齐";
                #region 计算文字宽度
                ////double dis = pen.MeasureText(mtext);
                //Vector2 lidisptpos = lcText.Start + (new Vector2(lcText.XLpoint.X * 100, lcText.XLpoint.Y * 100)) / Math.Sqrt(Math.Abs((Math.Pow(lcText.XLpoint.X, 2.0) + Math.Pow(lcText.XLpoint.Y, 2.0))));
                lcText.End = text.Position.ToVecror2d();
                #endregion

                lcElement = lcText;

            }
            else if (entity is BlockReference)
            {
                var blockReference = entity as BlockReference;
                LcBlock? lcBlock = null;
                foreach (var block in lcDocument.Blocks)
                {
                    if (blockReference.Name == block.Name)
                    {
                        lcBlock = block;
                        break;
                    }
                }
                if (lcBlock != null)
                {

                    var LcBlockRef = lcDocument.CreateObject<LcBlockRef>(lcBlock);
                    Vector2 vector2 = blockReference.Position.ToVecror2d();
                    LcBlockRef.Set(matrix: Matrix3.GetTranslate(vector2));
                    lcElement = LcBlockRef;
                }

            }
            #endregion
            if (lcElement != null)
            {
                #region 颜色转换

                System.Drawing.Color color;
                if (entity.Color.ColorNameForDisplay.ToUpper() == "BYLAYER")
                {
                    LayerTableRecord layerTableRecord = entity.LayerId.GetObject(OpenMode.ForRead) as LayerTableRecord;
                    color = layerTableRecord.Color.ColorValue;
                }
                else { color = entity.Color.ColorValue; }

                lcElement.Color = System.Drawing.ColorTranslator.ToHtml(color);
                #endregion
                lcElement.Layer = entity.Layer;
                lcElement.LineType = entity.Linetype;
                lcElement.LineWeight = entity.LineWeight.ToString();
            }

            return lcElement;
        }
        public static Vector2 ToVecror2d(this Point3d point3D)
        {
            return new Vector2(point3D.X, point3D.Y);
        }
        /// <summary>
        /// 线段转换
        /// </summary>
        /// <param name="lcDocument"></param>
        /// <param name="line"></param>
        /// <returns></returns>
        public static LcLine ConvertLineToLcLine(LcDocument lcDocument, Line line)
        {
            LcLine lcLine = lcDocument.CreateObject<LcLine>();
            lcLine.Start = ConvertPoint3DVector2d(line.StartPoint);
            lcLine.End = ConvertPoint3DVector2d(line.EndPoint);


            return lcLine;
        }
        public static LcEllipse ConvertEllipseToLcEllipse(LcDocument lcDocument, Ellipse ellipse)
        {
            var lcEllipse = lcDocument.CreateObject<LcEllipse>();
            lcEllipse.Center = ConvertPoint3DVector2d(ellipse.Center);
            lcEllipse.AxisX = new Vector2(ellipse.MajorAxis.X, ellipse.MajorAxis.Y).Normalize();
            lcEllipse.RadiusX = ellipse.MajorRadius;
            lcEllipse.RadiusY = ellipse.MinorRadius; ;
            lcEllipse.StartAngle = ellipse.StartAngle;
            lcEllipse.EndAngle = ellipse.EndAngle;
            return lcEllipse;
        }
        public static LcArc ConvertArcToLcArc(LcDocument lcDocument, Arc arc)
        {
            LcArc lcArc = lcDocument.CreateObject<LcArc>();
            lcArc.Startp = arc.StartPoint.ToVecror2d();
            lcArc.Endp = arc.EndPoint.ToVecror2d();
            lcArc.StartAngle = arc.StartAngle;
            lcArc.EndAngle = arc.EndAngle;
            lcArc.Radius = arc.Radius;
            lcArc.Center = arc.Center.ToVecror2d();
            return lcArc;
        }
        public static LcCircle ConvertCircleToLcCircle(LcDocument lcDocument, Circle circle)
        {
            LcCircle lcCircle = lcDocument.CreateObject<LcCircle>();
            lcCircle.Center = ConvertPoint3DVector2d(circle.Center);
            lcCircle.Radius = circle.Radius;
            return lcCircle;
        }
        public static LcPolyLine ConvertPolylineToLcPolyline(LcDocument lcDocument, Polyline polyline)
        {
            LcPolyLine lcPolyLine = lcDocument.CreateObject<LcPolyLine>();
            List<PlineSegment> Segments = new List<PlineSegment>();
            PlineSegment pl;

            DBObjectCollection oldCol = new DBObjectCollection();
            polyline.Explode(oldCol);



            Vector2? lastLineStartPoint = null;   //最后一个闭合线段的终点坐标
            Vector2? lastLineEndPoint = null;     //第一个线段的起点坐标
            foreach (DBObject obj in oldCol)
            {
                Curve crv = obj as Curve;
                if (crv != null)
                {


                    Point3d start = crv.StartPoint;
                    Point3d end = crv.EndPoint;

                    #region 特别注意，由于弧线的数据始终使用小角度作为StartPoint，所以会出现无法多段线中线段的起始点次序错乱的问题，这里进行强制的起始点换算

                    if (lastLineStartPoint != null)
                    {
                        if (
                            !(GeoUtils.AlmostEqual(lastLineStartPoint.X, start.X, 1) && GeoUtils.AlmostEqual(lastLineStartPoint.Y, start.Y, 1))
                            && !(GeoUtils.AlmostEqual(lastLineStartPoint.X, end.X, 1) && GeoUtils.AlmostEqual(lastLineStartPoint.Y, end.Y, 1))
                            )
                        {
                            var lastLine = Segments[Segments.Count - 1];
                            lastLine = new PlineSegment();
                            lastLine.Start = lastLine.End;
                            lastLine.End = lastLine.Start;
                            lastLineStartPoint = lastLine.End;
                        }
                        if (!(GeoUtils.AlmostEqual(lastLineEndPoint.X, start.X, 1) && GeoUtils.AlmostEqual(lastLineEndPoint.Y, start.Y, 1)))
                        {
                            if (GeoUtils.AlmostEqual(lastLineStartPoint.X, end.X, 2) && GeoUtils.AlmostEqual(lastLineStartPoint.Y, end.Y, 2))
                            {
                                start = crv.EndPoint;
                                end = crv.StartPoint;
                            }
                        }
                    }

                    #endregion 特别注意，由于弧线的数据始终使用小角度作为StartPoint，所以会出现无法多段线中线段的起始点次序错乱的问题，这里进行强制的起始点换算



                    if (!GeoUtils.AlmostEqual(start.X, end.X) || !GeoUtils.AlmostEqual(start.Y, end.Y))
                    {
                        PlineSegment plineSegment = new PlineSegment();
                        plineSegment.Start = ConvertPoint3DVector2d(start);
                        plineSegment.End = ConvertPoint3DVector2d(end);
                        if (crv is Line)
                        {
                        }
                        Segments.Add(plineSegment);
                        if (lastLineEndPoint == null)
                            lastLineEndPoint = new Vector2(start.X, start.Y);

                        lastLineStartPoint = new Vector2(end.X, end.Y);

                        double bulge = 0.0;
                        if (crv is Arc)
                        {
                            Arc arc = (Arc)crv;
                            if (!(arc.Radius > 100000 && GeoUtils.AlmostEqual(arc.StartAngle, arc.EndAngle, 4)))
                            {
                                double angle = arc.Center.GetVectorTo(start).GetAngleTo(arc.Center.GetVectorTo(end), arc.Normal);
                                bulge = Math.Tan(angle / 4.0);
                                plineSegment.Type = PlineSegmentType.Arc;
                                plineSegment.Center = new Vector2(arc.Center.X, arc.Center.Y);
                                double startAngle = arc.StartAngle < 0 ? arc.StartAngle + Math.PI * 2 : arc.StartAngle;
                                double entAngle = arc.EndAngle < 0 ? arc.EndAngle + Math.PI * 2 : arc.EndAngle;
                                plineSegment.StartAngle = arc.StartAngle;
                                plineSegment.EndAngle = arc.EndAngle;
                                plineSegment.Radius = arc.Radius;
                            }
                        }

                    }
                }
                obj.Dispose();
            }
            lcPolyLine.Segments = Segments;

            return lcPolyLine;
        }
        /// <summary>
        /// 标注转换
        /// </summary>
        /// <param name="lcDocument"></param>
        /// <param name="dimension"></param>
        /// <returns></returns>
        public static LcElement ConvertDimToLcDim(LcDocument lcDocument, Dimension dimension)
        {
            LcElement lcElement = null;
            //对齐
            if (dimension is AlignedDimension)
            {
                AlignedDimension alignedDimension = dimension as AlignedDimension;
                Vector2? startPoint = ConvertPoint3DVector2d(alignedDimension.XLine1Point);
                Vector2? endPoint = ConvertPoint3DVector2d(alignedDimension.XLine2Point);
                Vector2? dimPoint = ConvertPoint3DVector2d(alignedDimension.DimLinePoint);
                lcElement = lcDocument.CreateObject<DimAligned>(startPoint, endPoint, dimPoint);

            }
            //直径
            else if (dimension is DiametricDimension)
            {
                DiametricDimension diametricDimension = dimension as DiametricDimension;
                var dimDiametric = lcDocument.CreateObject<DimDiametric>();
                dimDiametric.Start = ConvertPoint3DVector2d(diametricDimension.ChordPoint);
                dimDiametric.End = ConvertPoint3DVector2d(diametricDimension.FarChordPoint);
                dimDiametric.Dimtext = diametricDimension.CurrentMeasurement.ToString("0.00");
                dimDiametric.Center = ConvertPoint3DVector2d(diametricDimension.TextPosition);
                lcElement = dimDiametric;
            }
            //半径
            else if (dimension is RadialDimension)
            {
                RadialDimension radial = dimension as RadialDimension;
                var dimRadial = lcDocument.CreateObject<DimRadial>();
                dimRadial.Start = ConvertPoint3DVector2d(radial.ChordPoint);
                dimRadial.End = ConvertPoint3DVector2d(radial.Center);
                dimRadial.Dimtext = radial.CurrentMeasurement.ToString("0.00");
                lcElement = dimRadial;
            }
            //角度
            else if (dimension is LineAngularDimension2)
            {
                LineAngularDimension2 cadDim = dimension as LineAngularDimension2;
                List<LcLine> lcLines = new List<LcLine>();
                LcLine lcLine = new LcLine(cadDim.XLine1Start.X, cadDim.XLine1Start.Y, cadDim.XLine1End.X, cadDim.XLine1End.Y);
                lcLines.Add(lcLine);
                LcLine lcLine2 = new LcLine(cadDim.XLine2Start.X, cadDim.XLine2Start.Y, cadDim.XLine2End.X, cadDim.XLine2End.Y);
                lcLines.Add(lcLine2);
                var centerp = DimAngularArc.GetLineIntersection(lcLine, lcLine2);
                var dimAngulararc = lcDocument.CreateObject<DimAngularArc>();
                dimAngulararc.selectLines = lcLines;
                dimAngulararc.Centerp = centerp;
                dimAngulararc.Movep = ConvertPoint3DVector2d(cadDim.ArcPoint);
                dimAngulararc.LoadDimAngleProperty();
                lcElement = dimAngulararc;

            }
            else if (dimension is Point3AngularDimension)
            {
                Point3AngularDimension cadDim = dimension as Point3AngularDimension;
                List<LcLine> lcLines = new List<LcLine>();
                LcLine lcLine = new LcLine(cadDim.XLine1Point.X, cadDim.XLine1Point.Y, cadDim.CenterPoint.X, cadDim.CenterPoint.Y);
                lcLines.Add(lcLine);
                LcLine lcLine2 = new LcLine(cadDim.XLine2Point.X, cadDim.XLine2Point.Y, cadDim.CenterPoint.X, cadDim.CenterPoint.Y);
                lcLines.Add(lcLine2);
                //var centerp = DimAngularArc.GetLineIntersection(lcLine, lcLine2);
                var dimAngulararc = lcDocument.CreateObject<DimAngularArc>();
                dimAngulararc.selectLines = lcLines;
                dimAngulararc.Centerp = ConvertPoint3DVector2d(cadDim.CenterPoint);
                dimAngulararc.Movep = ConvertPoint3DVector2d(cadDim.ArcPoint);
                dimAngulararc.LoadDimAngleProperty();
                lcElement = dimAngulararc;
            }
            //转角
            else if (dimension is RotatedDimension)
            {
                RotatedDimension rotatedDimension = dimension as RotatedDimension;
                Vector2? firstPoint = ConvertPoint3DVector2d(rotatedDimension.XLine1Point);
                Vector2? secondPoint = ConvertPoint3DVector2d(rotatedDimension.XLine2Point);
                Vector2? thirdPoint = ConvertPoint3DVector2d(rotatedDimension.TextPosition);
                bool vertical = false;

                if (firstPoint.X == secondPoint.X)
                {
                    vertical = false;
                }
                else if (firstPoint.Y == secondPoint.Y)
                {
                    vertical = true;
                }
                else if ((thirdPoint.X > firstPoint.X && thirdPoint.X < secondPoint.X) || (thirdPoint.X < firstPoint.X && thirdPoint.X > secondPoint.X))
                {
                    vertical = true;
                }
                else if ((thirdPoint.Y > firstPoint.Y && thirdPoint.Y < secondPoint.Y) || (thirdPoint.Y < firstPoint.Y && thirdPoint.Y > secondPoint.Y))
                {
                    vertical = false;
                }
                var dimRotated = lcDocument.CreateObject<DimRotated>(firstPoint, secondPoint, thirdPoint, vertical);
                lcElement = dimRotated;

            }
            //坐标
            else if (dimension is OrdinateDimension)
            {
                OrdinateDimension ordinateDimension = (OrdinateDimension)dimension;
                var dimOrdinate = lcDocument.CreateObject<DimOrdinate>();
                dimOrdinate.Start = ConvertPoint3DVector2d(ordinateDimension.DefiningPoint);
                dimOrdinate.End = ConvertPoint3DVector2d(ordinateDimension.LeaderEndPoint);
                dimOrdinate.second = ConvertPoint3DVector2d(ordinateDimension.TextPosition);
                lcElement = dimOrdinate;
            }
            return lcElement;
        }
        public static Vector2 ConvertPoint3DVector2d(Point3d point3D)
        {
            return new Vector2(point3D.X, point3D.Y);
        }
    }
}
